#include "TcpServer.h"
#include <iostream>
#include "File.h"

using std::cout;
using std::endl;

TcpServer::TcpServer(string ip, int port)
:epoll_()
,acceptor_(ip, port, epoll_)
{
}

void TcpServer::start()
{
	acceptor_.setAcceptorCb(std::bind(&TcpServer::AcceptorCb, this));
    while(1)
    {
        epoll_.loop();
    }
}

void TcpServer::AcceptorCb()
{
	int fd = acceptor_.accept();
	if (fd <= 0)
	{
		return;
	}

    Socket::getPeerAddr(fd).printAddr();
	shared_ptr<TcpConnection> pconn(new TcpConnection(fd, Socket::getPeerAddr(fd), epoll_));	
	pconn->socktype_ = esock_connected;

    shared_ptr<Channel> pchannel(new Channel());
    pchannel->onConnCb_ = std::bind(&TcpServer::OnConnectionCb, this, pconn);
    pchannel->onMessCb_ = std::bind(&TcpServer::OnMessageCb, this, pconn);
    pchannel->onCloseCb_ = std::bind(&TcpServer::OnCloseCb, this, pconn);
	epoll_.epollAdd(fd, &*pconn, pchannel);
	map_.insert(make_pair(fd, pconn));

    pchannel->onConnCb_();
}

void TcpServer::OnConnectionCb(shared_ptr<TcpConnection> &pconn)
{
	/*
    string s("Hello World");
    pconn->sendTcpData(s);
	*/
	sendFile(pconn);
}

void TcpServer::OnMessageCb(shared_ptr<TcpConnection> &pconn)
{
	uint32_t events = pconn->events;
	bool evRead = events | EPOLLIN || events | EPOLLHUP;
	bool evWrite = events | EPOLLOUT;
	bool evErr = events | EPOLLERR;

	if (evRead)
	{
		pconn->readTcpData();
		queue<string> &queue = pconn->getReadQueue();
		while (!queue.empty())
		{
			string &tmp = queue.front();
			cout << tmp << endl;
			queue.pop();
		}
        if (!evWrite)
        {
            return;
        }
	}
	if (evWrite)
	{
        pconn->sendTcpQueue();
        return;
	}
	if (evErr)
	{
        OnCloseCb(pconn);
	}
}

void TcpServer::OnCloseCb(shared_ptr<TcpConnection> &pconn)
{
    Socket &sock = pconn->sockfd_;
    
    epoll_.epollDel(sock.fd());
    map_.erase(sock.fd());
    cout << pconn.use_count() << endl;
}

int main()
{
    TcpServer server("127.0.0.1", 8888);
    server.start();
    return 0;
}
